#include "pch.h"

#include "math/directx/dxplane.h"
#include "core/config.h"


#ifdef RE_USE_DX

namespace Math
{

	//////////////////////////////////////////////////////////////////////////
	plane::plane()
	{
		// TODO
	}

	//////////////////////////////////////////////////////////////////////////
	plane::plane( scalar a, scalar b, scalar c, scalar d )
	{
		this->m_vec = XMVectorSet(a, b, c, d);
	}

	//////////////////////////////////////////////////////////////////////////
	plane::plane( const float4& p0, const float4& p1, const float4& p2 )
	{
		this->m_vec = XMPlaneFromPoints(p0.m_vec, p1.m_vec, p2.m_vec);
	}

	//////////////////////////////////////////////////////////////////////////
	plane::plane( const float4& p, const float4& n )
	{
		this->m_vec = XMPlaneFromPointNormal(p.m_vec, n.m_vec);
	}

	//////////////////////////////////////////////////////////////////////////
	plane::plane( XMVECTOR rhs ):
	m_vec(rhs)
	{
		// TODO
	}





	//////////////////////////////////////////////////////////////////////////
	void plane::set( scalar a, scalar b, scalar c, scalar d )
	{
		this->m_vec = XMVectorSet(a, b, c, d);
	}

	//////////////////////////////////////////////////////////////////////////
	void plane::setA( scalar a )
	{
		this->m_vec = XMVectorSetXPtr(this->m_vec, &a);
	}

	//////////////////////////////////////////////////////////////////////////
	void plane::setB( scalar b )
	{
		this->m_vec = XMVectorSetYPtr(this->m_vec, &b);
	}

	//////////////////////////////////////////////////////////////////////////
	void plane::setC( scalar c )
	{
		this->m_vec = XMVectorSetZPtr(this->m_vec, &c);
	}

	//////////////////////////////////////////////////////////////////////////
	void plane::setD( scalar d )
	{
		this->m_vec = XMVectorSetWPtr(this->m_vec, &d);
	}

	//////////////////////////////////////////////////////////////////////////
	scalar& plane::getA()
	{
		return this->m_vec.m128_f32[0];
	}

	//////////////////////////////////////////////////////////////////////////
	scalar& plane::getB()
	{
		return this->m_vec.m128_f32[1];
	}

	//////////////////////////////////////////////////////////////////////////
	scalar& plane::getC()
	{
		return this->m_vec.m128_f32[2];
	}

	//////////////////////////////////////////////////////////////////////////
	scalar& plane::getD()
	{
		return this->m_vec.m128_f32[3];
	}

	//////////////////////////////////////////////////////////////////////////
	scalar plane::getA() const
	{
		return float4::unwrapx(this->m_vec);
	}

	//////////////////////////////////////////////////////////////////////////
	scalar plane::getB() const
	{
		return float4::unwrapy(this->m_vec);
	}

	//////////////////////////////////////////////////////////////////////////
	scalar plane::getC() const
	{
		return float4::unwrapz(this->m_vec);
	}

	//////////////////////////////////////////////////////////////////////////
	scalar plane::getD() const
	{
		return float4::unwrapw(this->m_vec);
	}

	//////////////////////////////////////////////////////////////////////////
	scalar plane::dot( const float4& f ) const
	{
		return float4::unwrapw(XMPlaneDot(this->m_vec, f.m_vec));
	}





	//////////////////////////////////////////////////////////////////////////
	bool plane::intersectline( const float4& start, const float4& end, float4& outPoint )
	{
		outPoint = XMPlaneIntersectLine(this->m_vec, start.m_vec, end.m_vec);

		if(XMPlaneIsNaN(outPoint.m_vec))
			return false;
		else
			return true;
	}

	//////////////////////////////////////////////////////////////////////////
	plane plane::normalize( const plane& p )
	{
		return XMPlaneNormalize(p.m_vec);
	}

	//////////////////////////////////////////////////////////////////////////
	plane plane::transform( const plane& p, const matrix& m )
	{
		return XMPlaneTransform(p.m_vec, m.m_matrix);
	}

}

#endif // RE_USE_DX